package cn.touna.jss.modules.third.yixin.util;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;

public class YiXinUtil {

    private static final String RC4 = "RC4"; //RC4
    private static final String UTF8 = "UTF-8";//编码格式
    private static final String RSA = "RSA";//RSA

    private static final Logger logger = LoggerFactory.getLogger(YiXinUtil.class);

    /**
     * RC4加密明文（可能包含汉字），输出是经过Base64的；如果加密失败，返回值是null
     *
     * @param plainText
     * @param rc4Key
     * @return
     */
    public static final String encodeByRC4(final String plainText, final String rc4Key) {
        try {
            final Cipher c1 = Cipher.getInstance(RC4);
            c1.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(rc4Key.getBytes(), RC4));
            return new String(Base64.encodeBase64(c1.doFinal(plainText.getBytes(UTF8))));
        } catch (Throwable t) {
            //		logger.error("", t);
            return null;
        }
    }

    /**
     * RC4从密文解密为明文，输入是经过Base64的；如果解密失败，返回值是null
     *
     * @param encodedText
     * @param rc4Key
     * @return
     */
    public static final String decodeByRC4(final String encodedText, final String rc4Key) {
        try {
            final Cipher c1 = Cipher.getInstance(RC4);
            c1.init(Cipher.DECRYPT_MODE, new SecretKeySpec(rc4Key.getBytes(), RC4));
            return new String(c1.doFinal(Base64.decodeBase64(encodedText.getBytes())), UTF8);
        } catch (Throwable t) {
            //	logger.error("", t);
            return null;
        }
    }

    /**
     * RSA公钥加密明文，输出是经过Base64的；如果加密失败，返回值是null
     *
     * @param publicKey
     * @param plainText
     * @return
     */
    public static final String encodeByRSAPublicKey(final RSAPublicKey publicKey, final String plainText) {
        try {
            final Cipher cipher = Cipher.getInstance(RSA);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return new String(Base64.encodeBase64(cipher.doFinal(plainText.getBytes(UTF8))));
        } catch (Throwable t) {
            //logger.error("", t);
            return null;
        }
    }

    /**
     * 从CRT文件中，获取公钥；其实就是Java的反序列化过程
     *
     * @param crtFilePath
     * @return
     */
    public static final RSAPublicKey gainRSAPublicKeyFromCrtFile(final String crtFilePath) {
        RSAPublicKey publicKey = null;
        ObjectInputStream ois = null;

        try {
            final File crtFile = new File(crtFilePath);
            ois = new ObjectInputStream(new FileInputStream(crtFile));
            publicKey = (RSAPublicKey) ois.readObject();
            ois.close();
        } catch (Throwable t) {
            //logger.error("", t);
            ois = null;
        }
        return publicKey;
    }

    /**
     * 从PEM文件中，获取公钥
     *
     * @param pemFilePath
     * @return
     */
    public static final RSAPublicKey gainRSAPublicKeyFromPemFile(final String pemFilePath) {
//System.out.println("pemFilePath="+pemFilePath);
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(pemFilePath));
            String s = br.readLine();
            StringBuilder sb = new StringBuilder();
            s = br.readLine();
            while (s.charAt(0) != '-') {
                sb.append(s).append("\r");
                s = br.readLine();
            }
            br.close();
            //生成公匙
            KeyFactory kf = KeyFactory.getInstance(RSA);
            return (RSAPublicKey) (kf.generatePublic(new X509EncodedKeySpec(cn.touna.jss.common.util.Base64.decode(sb.toString()))));
        } catch (Throwable t) {
            logger.error(t.getMessage());
            br = null;
            return null;
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    logger.error(e.getMessage());
                }
            }
        }
    }

    /**
     * 直接拿到秘钥生成公匙对象
     *
     * @param pemFilePath
     * @return
     */
    public static final RSAPublicKey gainRSAPublicKey(final String pemKey) {
        try {
            //生成公匙
            KeyFactory kf = KeyFactory.getInstance(RSA);
            return (RSAPublicKey) (kf.generatePublic(new X509EncodedKeySpec(cn.touna.jss.common.util.Base64.decode(pemKey))));
        } catch (Throwable t) {
            return null;
        }
    }
}
